package com.geekchique.runningbuddy.controller;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.geekchique.runningbuddy.R;
import android.graphics.BitmapFactory;
import android.location.Location;
import android.location.LocationManager;
import android.os.Handler;
import android.view.KeyEvent;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.util.Log;

import com.geekchique.runningbuddy.activity.MapOfJogs;
import com.geekchique.runningbuddy.model.Jog;
import com.geekchique.runningbuddy.model.ListOfJogs;
import com.geekchique.runningbuddy.util.DBHelperImpl;
import com.geekchique.runningbuddy.util.IDBHelper;
import com.geekchique.runningbuddy.view.MapOfJogsView;
import com.geekchique.runningbuddy.view.overlay.MapOfJogsOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayController;
import com.google.android.maps.Point;

public class MapOfJogsControllerImpl implements IMapOfJogsController {

	public MapOfJogsView mapOfJogView;
	private MapController mapViewController;
	private MapOfJogs mapOfJogActivity;
	private Spinner pointCollectionList;
	private OverlayController overlayController;
	public Location currentGPSLocationOfPhone = null;
	protected LocationManager locationManager = null;
	protected IDBHelper dbHelper;
	public ListOfJogs listOfJogs;
	final Handler mHandler;

    protected List<Location> path = new ArrayList<Location>();

	private String[][] locations = 	{
			  { "Tullis", "-4.229920, 55.846809" },
	          { "Glasgow Green", "-4.232676, 55.846904" }
		};
	private MapOfJogsOverlay googleMapOverlay;

	public MapOfJogsControllerImpl(MapOfJogs mapOfJog) {
		this.mapOfJogActivity = mapOfJog;
		this.mHandler = new Handler();
		this.dbHelper = new DBHelperImpl(mapOfJog);
	}

	public void createMapOfJogView(MapView mapView, Spinner pointCollection, int spinnerDropDownItems, Button goButton, int day, int month, int year) {
		this.mapOfJogView = new MapOfJogsView(mapOfJogActivity, this, goButton, mapView);
		this.pointCollectionList = pointCollection;
		this.mapViewController = mapView.getController();
	    this.listOfJogs = dbHelper.fetchAllJogEntries(day, month, year);

	    locations = listOfJogs.toArray();

		setSpinnerPresenter(populateSpinnerListPresenter(mapOfJogActivity, spinnerDropDownItems, locations));

		this.overlayController = mapView.createOverlayController();

		this.googleMapOverlay =
			new MapOfJogsOverlay(
					this.mapOfJogActivity,
					BitmapFactory.decodeResource(this.mapOfJogActivity.getResources(), R.drawable.map_start_point),
					BitmapFactory.decodeResource(this.mapOfJogActivity.getResources(), R.drawable.map_stop_point),
					BitmapFactory.decodeResource(this.mapOfJogActivity.getResources(), R.drawable.dial)
			);

		overlayController.add(googleMapOverlay, true);

    	centerTheScreenOnTheLastJogRoute();

	}




	private void centerTheScreenOnTheLastJogRoute() {
		Location pointLocation = new Location();
    	pointLocation.setLatitude(55.846904);
    	pointLocation.setLongitude(-4.232676);
    	setCurrentGPSLocationOfPhone(pointLocation);
    	gotoCurrentGPSPosition();
	}

	public void plotChosenJog(){
		drawCurrentlySelectedJogPath();
		//gotoCurrentlySelected();
	}

	private void drawCurrentlySelectedJogPath() {
		this.googleMapOverlay.path.clear();
		path.clear();
		Jog jog = listOfJogs.get(this.pointCollectionList.getSelectedItemPosition());
		Map<Long, Location> locationsAndTimes = jog.getlocationsAndTimes();

		for (Iterator<Map.Entry<Long, Location>> it=locationsAndTimes.entrySet().iterator(); it.hasNext(); ) {
	        Map.Entry<Long, Location> entry = (Map.Entry<Long, Location>)it.next();
	        Location location = entry.getValue();
	        addPoint(location);
	        setCurrentGPSLocationOfPhone(location);
	    }

		gotoCurrentGPSPosition2();

	}

	private ArrayAdapter<CharSequence> populateSpinnerListPresenter(MapActivity mapOfJogActivity, int spinnerDropDownListID, String[][] locations) {
		ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>( mapOfJogActivity, spinnerDropDownListID);

		for (int i = 0; i < locations.length; i++){
			adapter.addObject(locations[i][0]);
		}

		adapter.setDropDownViewResource(spinnerDropDownListID);
		return adapter;
	}

	private void setSpinnerPresenter(ArrayAdapter<CharSequence> adapter) {
	      this.pointCollectionList.setAdapter(adapter);
	}

	public void gotoCurrentlySelected() {
		Location mapPoint = getMapPointFromLocationList(this.pointCollectionList.getSelectedItemPosition());
		
		setCurrentGPSLocationOfPhone(mapPoint);
		gotoCurrentGPSPosition();
	}


	public void gotoCurrentGPSPosition() {

		Point point = new Point((int) (this.currentGPSLocationOfPhone.getLatitude() * 1000000), (int) (this.currentGPSLocationOfPhone.getLongitude() * 1000000));

		mapViewController.animateTo(point);
		mapViewController.zoomTo(18);
		mapOfJogView.invalidateMapView();

	}

	public void gotoCurrentGPSPosition2() {

		Point point = new Point((int) (this.currentGPSLocationOfPhone.getLatitude()), (int) (this.currentGPSLocationOfPhone.getLongitude()));

		mapViewController.animateTo(point);
		mapViewController.zoomTo(18);
		mapOfJogView.invalidateMapView();

	}

	private Location getMapPointFromLocationList(int pos) {
		String[] loc = locations[pos][1].split(",");

		double lat = Double.parseDouble(loc[1]);
		double lon = Double.parseDouble(loc[0]);

    	Location pointLocation = new Location();
    	pointLocation.setLatitude(lat);
    	pointLocation.setLongitude(lon);

    	return pointLocation;
	}

	public void zoomTo(int zoomLevel) {
		this.mapViewController.zoomTo(zoomLevel);
	}

	public boolean onKeyDown(int keyCode, KeyEvent event) {

			switch (keyCode) {
				case KeyEvent.KEYCODE_I:
						mapViewController.zoomTo(mapOfJogView.getZoomLevel() + 1);
						break;
				case KeyEvent.KEYCODE_O:
						mapViewController.zoomTo(mapOfJogView.getZoomLevel() - 1);
						break;
				case KeyEvent.KEYCODE_V:
					draw1Point();
					break;
				case KeyEvent.KEYCODE_B:
					draw2Point();
					break;
				case KeyEvent.KEYCODE_N:
					draw3Point();
					break;
				case KeyEvent.KEYCODE_M:
					draw4Point();
					break;
				case KeyEvent.KEYCODE_L:
					this.googleMapOverlay.path.clear();
					drawPoints();
					break;
				case KeyEvent.KEYCODE_P:
					this.googleMapOverlay.path.clear();
					drawPoints2();
					break;
				case KeyEvent.KEYCODE_Q:
					this.googleMapOverlay.path.clear();
					drawPathFromDB2();
					break;
				case KeyEvent.KEYCODE_S:
					mapOfJogView.toggleSatellite();
					break;
				case KeyEvent.KEYCODE_BACK:
					this.overlayController.deactivate(this.googleMapOverlay);
		      }

		      return true;
	}

	private void drawPathFromDB2() {
		path.clear();
		Jog jog = listOfJogs.getLast();
		Map<Long, Location> locationsAndTimes = jog.getlocationsAndTimes();

		for (Iterator<Map.Entry<Long, Location>> it=locationsAndTimes.entrySet().iterator(); it.hasNext(); ) {
			Map.Entry<Long, Location> entry = (Map.Entry<Long, Location>)it.next();
			Location location = entry.getValue();
			addPoint(location);
			setCurrentGPSLocationOfPhone(location);
		}

		gotoCurrentGPSPosition2();

	}

	public void draw1Point() {
		addPoint(55846809, -4229920);
	}

	public void draw2Point() {
		addPoint(55846809, -4231200);
	}

	public void draw3Point() {
		addPoint(55851200, -4236400);
	}

	public void draw4Point() {
		addPoint(55851000, -4236800);
	}


    private boolean addPoint(double latitude, double longitude) {
    	Location pointLocation = new Location();
    	pointLocation.setLatitude(latitude);
    	pointLocation.setLongitude(longitude);
    	this.googleMapOverlay.addLocationToPath(pointLocation);
		mapOfJogView.invalidateMapView();
    	return true;
    }

    private boolean addPoint(Location location) {
    	this.googleMapOverlay.addLocationToPath(location);
    	mapOfJogView.invalidateMapView();
    	return true;
    }

	public void drawPoints() {
		path.clear();
		draw1Point();
		draw2Point();
		draw3Point();
		draw4Point();
	}

	public void drawPoints2() {
		path.clear();
		draw2Point();
		draw4Point();
		draw1Point();
		draw3Point();
	}

	public void updateRunningPath() {
		if(this.currentGPSLocationOfPhone != null){
	    	Location pointLocation = new Location();
	    	pointLocation.setLatitude(this.currentGPSLocationOfPhone.getLatitude() * 1000000);
	    	pointLocation.setLongitude(this.currentGPSLocationOfPhone.getLongitude() * 1000000);
	    	this.googleMapOverlay.addLocationToPath(pointLocation);
			gotoCurrentGPSPosition();
		}
	}

	public void setCurrentGPSLocationOfPhone(Location currentLocation) {
		this.currentGPSLocationOfPhone = currentLocation;
	}

}
